import { Injectable } from '@nestjs/common';
import { Like, Repository, Between } from 'typeorm';
import WipAlarmRecord from '@main/entities/service/admin/wip/wip-alarm-record.entity';
import BaseMachine from '@main/entities/service/admin/base/base-machine.entity';
import SysDictionary from '@main/entities/service/admin/sys/sys-dictionary.entity';
import { UtilService } from '@main/shared/services/util.service';
import { InjectRepository } from '@nestjs/typeorm';
import { ApiException } from '@main/common/exceptions/api.exception';
import { generateExcelFn } from '@main/excel';
import { SysOperationLogService } from '../../system/operationLog/operationLog.service';
import { format } from 'date-fns';

@Injectable()
export class WipAlarmRecordService {
  constructor(
    @InjectRepository(WipAlarmRecord)
    private alarmRecordRepository: Repository<WipAlarmRecord>,
    private util: UtilService,
    private operationLogService: SysOperationLogService,
    @InjectRepository(BaseMachine)
    private machineRepository: Repository<BaseMachine>,
    @InjectRepository(SysDictionary)
    private dictionaryRepository: Repository<SysDictionary>
  ) {}

  async list() {
    return await this.alarmRecordRepository.find();
  }

  /**
   * 罗列所有配置
   */
  async page(data, lang) {
    const { pageSize, pageNum, entity = {} } = data;

    const { machineCode, createTime } = entity;

    const where = {
      machineCode: Like(`%${machineCode}%`),
    };

    if (createTime && createTime.length) {
      where['createTime'] = Between(createTime[0], createTime[1]);
    }

    const [list, total] = await this.alarmRecordRepository.findAndCount({
      where,
      order: {
        updateTime: 'DESC',
      },
      take: pageSize,
      skip: (pageNum - 1) * pageSize,
    });

    const newList = await Promise.all(
      list?.map(async (item) => {
        const { alarmTypeCode, alarmStatusCode, machineCode, occurTime, closeTime } = item;
        if (occurTime) {
          item.occurTime = format(new Date(occurTime), 'yyyy-MM-dd HH:mm:ss');
        }
        if (closeTime) {
          item.closeTime = format(new Date(closeTime), 'yyyy-MM-dd HH:mm:ss');
        }
        const obj = await this.machineRepository.findOne({ where: { machineCode } });

        let alarmType = await this.dictionaryRepository.find({
          where: { dictionaryTypeCode: 'alarm_type', languageType: lang },
        });
        item.alarmTypeName =
          alarmType
            ?.map((item) => {
              return {
                label: item.dictionaryName,
                value: item.dictionaryCode,
              };
            })
            ?.find((item) => item.value === alarmTypeCode)?.label || '-';

        let alarmStatus = await this.dictionaryRepository.find({
          where: { dictionaryTypeCode: 'alarm_status', languageType: lang },
        });
        item.alarmStatusName =
          alarmStatus
            ?.map((item) => {
              return {
                label: item.dictionaryName,
                value: item.dictionaryCode,
              };
            })
            ?.find((item) => item.value === alarmStatusCode)?.label || '-';

        return {
          ...(obj || {}),
          ...item,
        };
      })
    );

    return [newList, total];
  }

  async export(dto, lang) {
    const [list] = await this.page(dto, lang);

    if (!list || !(list as any).length) {
      throw new ApiException(10052);
    }

    const dataList = list;

    return await generateExcelFn(
      {
        sheetName: 'alarmRecord',
        mainHeaderList: [
          {
            label: 'alarmRecordCode',
          },
          {
            label: 'alarmStatusName',
          },
          {
            label: 'machineCode',
          },
          {
            label: 'machineName',
          },
          {
            label: 'alarmTypeName',
          },
          {
            label: 'alarmArea',
          },
          {
            label: 'alarmCode',
          },
          {
            label: 'alarmName',
          },
          {
            label: 'occurTime',
          },
          {
            label: 'closeTime',
          },
        ],
        dataList,
      },
      lang
    );
  }

  /**
   * 新增
   */
  async add(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const alarmRecordCode = `BJ${this.util.nowDateValue()}${this.util.generateRandomNumberValue(
      4
    )}`;

    const { alarmStatus, machineCode, alarmCode, alarmName, alarmArea, alarmTypeCode } = data;

    const alarmRecord = await this.alarmRecordRepository.insert({
      alarmRecordCode,
      alarmStatusCode: alarmStatus,
      machineCode,
      alarmCode,
      alarmName,
      alarmArea,
      alarmTypeCode,
      occurTime: new Date().getTime(),
      createName: user?.nickName || null,
      createUserName: user?.userName || null,
      updateName: user?.nickName || null,
      updateUserName: user?.userName || null,
    });
    databaseOperationLogList.push({
      type: 'add',
      dataType: 'obj',
      database: 'WipAlarmRecord',
      checkOnlyKeyList: [],
      data: alarmRecord,
      whereObj: null,
      remark: `WipAlarmRecord表新增数据`,
    });

    await this.operationLogService.add(
      {
        type: 'add',
        msg: `报警记录管理模块新增报警记录`,
        databaseOperationLogList,
        remark: `新增报警记录${data.alarmRecordCode}`,
        mac,
        ip,
        syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
      },
      user
    );
  }

  /**
   * 更新
   */
  async update(data, user, mac, ip, syncHostSqlite) {
    const databaseOperationLogList = [];
    const { machineCode, changeAlarmList } = data;

    await Promise.all(
      changeAlarmList.map(async (item) => {
        const { alarmCode, alarmStatus } = item;

        const obj = await this.alarmRecordRepository.findOne({
          where: { machineCode, alarmCode },
          order: {
            updateTime: 'DESC',
          },
        });

        if (obj) {
          const { alarmStatusCode, closeTime, id } = obj;

          if (alarmStatus === '0') {
            if (!closeTime && alarmStatusCode !== '0') {
              await this.alarmRecordRepository.update(
                {
                  id,
                },
                {
                  closeTime: new Date().getTime(),
                  alarmStatusCode: alarmStatus,
                  updateName: user?.nickName || null,
                  updateUserName: user?.userName || null,
                }
              );
              databaseOperationLogList.push({
                type: 'update',
                dataType: 'obj',
                database: 'WipAlarmRecord',
                checkOnlyKeyList: [],
                data: {
                  closeTime: new Date().getTime(),
                  alarmStatusCode: alarmStatus,
                  updateName: user?.nickName || null,
                  updateUserName: user?.userName || null,
                },
                whereObj: { id },
                remark: `WipAlarmRecord表更新报警记录信息`,
              });
              await this.operationLogService.add(
                {
                  type: 'update',
                  msg: `报警记录管理模块更新报警记录`,
                  databaseOperationLogList,
                  remark: `更新报警记录${data.alarmRecordCode}`,
                  mac,
                  ip,
                  syncHostSqlite: isNaN(Number(syncHostSqlite)) ? 0 : Number(syncHostSqlite),
                },
                user
              );
            }
          } else if (alarmStatus === '1') {
            if (alarmStatusCode !== '1') {
              await this.add(item, user, mac, ip, syncHostSqlite);
            }
          }
        } else {
          if (alarmStatus === '1') {
            await this.add(item, user, mac, ip, syncHostSqlite);
          }
        }
      })
    );
  }
}
